﻿using C1.WPF;
using C1.WPF.Chart;
using C1.WPF.Chart.Annotation;
using C1.WPF.Chart.Interaction;
using Model.Modules;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Annotations;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;

using Utility;
using Proxy;

namespace SteelDetection.UIControl
{
    /// <summary>
    /// Flexchart.xaml 的交互逻辑
    /// </summary>
    public partial class UCRulerchart : UserControl
    {
        bool plus = true;
        Double Y = 0;
        public UCRulerchart()
        {
            InitializeComponent();
            canvas.DataContext = this;
            BackgroundWorker worker = new BackgroundWorker();
            Loaded += UCRulerchart_Loaded;
            Unloaded += UCRulerchart_Unloaded;

        }

        private void UCRulerchart_Unloaded(object sender, RoutedEventArgs e)
        {
            //Logger.Info("UCRulerchart_Unloaded");
            
        }

        private void UCRulerchart_Loaded(object sender, RoutedEventArgs e)
        {
            var defectinfos=annolayer.Annotations.Where(t => t is Shape).Select(s => (s as Shape).GetValue(TagProperty) as DefectAnnoInfo ).ToList<DefectAnnoInfo>();
            annolayer.Annotations.Clear();
            AddDefects(defectinfos.ToList());
            //Logger.Info("UCRulerchart_Loaded");
        }

        Defectypes defectypes = Defectypes.GetInstance();
        #region DependencyProperty定义
        public string ChartName
        {
            get
            {
                return (string)GetValue(ChartNameProperty);
            }
            set
            {
                SetValue(ChartNameProperty, value);


            }
        }
        public static readonly DependencyProperty ChartNameProperty = DependencyProperty.RegisterAttached("ChartName", typeof(string), typeof(UCRulerchart), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, new PropertyChangedCallback((d, e) =>
        {

        })));

        public bool CanInteract
        {
            get
            {
                return (bool)GetValue(CanInteractProperty);
            }
            set
            {
                SetValue(CanInteractProperty, value);


            }
        }
        public static readonly DependencyProperty CanInteractProperty = DependencyProperty.RegisterAttached("CanInteract", typeof(bool), typeof(UCRulerchart), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, new PropertyChangedCallback((d, e) =>
        {

        })));

        public bool ShowScanLine
        {
            get
            {
                return (bool)GetValue(ShowScanLineProperty);
            }
            set
            {
                SetValue(ShowScanLineProperty, value);


            }
        }
        public static readonly DependencyProperty ShowScanLineProperty = DependencyProperty.RegisterAttached("ShowScanLine", typeof(bool), typeof(UCRulerchart), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, new PropertyChangedCallback((d, e) =>
        {

        })));

        #endregion


        public void ClearAnno()
        {
            annolayer.Annotations.Clear();
        }
        
        private SolidColorBrush getColorByType(int typeid)
        {
            var colorstr = "Green";
            var list = defectypes.Where(t => t.id == typeid);
            if (list.Count() == 1)
                colorstr=list.First().color;
            return new SolidColorBrush((Color)System.Windows.Media.ColorConverter.ConvertFromString(colorstr));
        }
        private SolidColorBrush getFillColorByType(int typeid)
        {
            var colorstr = "#00FF00";
            var list = defectypes.Where(t => t.id == typeid);
            if (list.Count() == 1)
                colorstr = list.First().color;
            colorstr = colorstr.Insert(1, "77");
            return new SolidColorBrush((Color)System.Windows.Media.ColorConverter.ConvertFromString(colorstr));
        }
        public bool setNormalStyle(Shape shape)
        {
            if (shape != null)
            {
                shape.Style.StrokeThickness = 1;
                shape.Style.Fill = getFillColorByType((shape.GetValue(TagProperty) as DefectAnnoInfo).type);
            }
            return true;
        }
        public bool setHighLightStyle(Shape shape)
        {
            if (shape != null)
            {
                shape.Style.LinePattern = C1.Chart.LinePatternEnum.Solid;
                shape.Style.StrokeThickness = 8;
                shape.Style.Fill = new SolidColorBrush();
            }
            return true;
        }

        public void AddRectAnno(Rect rect, int type)
        {
            annolayer.Annotations.Add(
                new C1.WPF.Chart.Annotation.Rectangle()
                {
                    Attachment = C1.Chart.Annotation.AnnotationAttachment.DataCoordinate,
                    Position = C1.Chart.Annotation.AnnotationPosition.Center,
                    Location = new Point(rect.X,rect.Y),
                    Width = rect.Width,
                    Height = rect.Height,
                    
                    //Content = DataConverter.ConvertTypeToIconStr(type),
                    Style = chartStyle,
                    ContentStyle = contentStyle,
                    TooltipText = DataConverter.ConvertTypeToName(type)
                }
            );

        }
        //SolidColorBrush Fillbrush = new SolidColorBrush(Colors.Transparent);
        //SolidColorBrush Strokebrush = new SolidColorBrush(Colors.Transparent);
        //SolidColorBrush Iconbrush = new SolidColorBrush(Color.FromArgb(100, 150, 255, 255));
        //FontFamily IconFont = new FontFamily("iconfont");
        C1.WPF.Chart.ChartStyle chartStyle = new C1.WPF.Chart.ChartStyle()
        {
            Fill = new SolidColorBrush(Colors.Transparent),
            Stroke = new SolidColorBrush(Colors.Transparent),

        };
        C1.WPF.Chart.ChartStyle contentStyle = new C1.WPF.Chart.ChartStyle
        {
            FontFamily = new FontFamily("iconfont"),
            FontSize = 16,
            Stroke = new SolidColorBrush(Color.FromArgb(100, 150, 255, 255))
        };
       
        public void AddIconFont(Point p, double type)
        {
            annolayer.Annotations.Add(
                new C1.WPF.Chart.Annotation.Rectangle()
                {
                    Attachment = C1.Chart.Annotation.AnnotationAttachment.DataCoordinate,
                    Position = C1.Chart.Annotation.AnnotationPosition.Center,
                    Location = p,
                    Width = 20,
                    Height = 20,
                    Content = DataConverter.ConvertTypeToIconStr(type),
                    Style = chartStyle,
                    ContentStyle = contentStyle,
                    TooltipText = DataConverter.ConvertTypeToName(type)
                }
            );
        }

        public void UpdateScanLine(int y)
        {
            scanline.Location = new Point(scanline.Location.X, y);
            annolayer.Annotations.Remove(scanline);
            annolayer.Annotations.Add(scanline);

        }
        public void RemoveScanLine()
        {
            if (scanline != null)
            {
                annolayer.Annotations.Remove(scanline);
            }
        }

        public void setActiveAnno(C1.WPF.Chart.Annotation.Rectangle activeanno)
        {
            foreach(var anno in annolayer.Annotations)
            {
                (anno as C1.WPF.Chart.Annotation.Rectangle).Style.StrokeThickness = 2;
            }
            activeanno.Style.StrokeThickness = 5;
        }


        public void AddDefect(DefectAnnoInfo defectAnno)
        {
            var r = defectAnno.rect;
            var typeid = defectAnno.type;
            rulerchart.BeginUpdate();
            var rect = new C1.WPF.Chart.Annotation.Rectangle()
            {
                Attachment = C1.Chart.Annotation.AnnotationAttachment.DataCoordinate,
                Position = C1.Chart.Annotation.AnnotationPosition.Center,
                Location = new Point(r.Left + r.Width / 2, r.Top + r.Height / 2),



                Style = new C1.WPF.Chart.ChartStyle()
                {
                    Stroke = getColorByType(typeid),
                    StrokeThickness=2
                },


            };
            rect.SetValue(TagProperty, defectAnno);
            annolayer.Annotations.Add(rect);
            //extendAxis(r);
            rulerchart.EndUpdate();
        }
        public void AddDefects(List<DefectAnnoInfo> defectAnnos)
        {
            if (!defectAnnos.Any())
                return;
            rulerchart.BeginUpdate();
            Stopwatch stopwatch = Stopwatch.StartNew();
            foreach (var defectAnno in defectAnnos) {
                if (StaticData.ShownMode == ShownMode.Icon)
                    AddDefectsAsIcon(defectAnno);
                else
                    AddDefectsAsRectangle(defectAnno);
            }
            //extendAxis(new Rect(0,0, defectAnnos.Max(t=>t.rect.Right), defectAnnos.Max(t => t.rect.Bottom)));
            stopwatch.Stop();
            rulerchart.EndUpdate();
            //rulerchart.Invalidate();

        }

        public void AddDefectsAsRectangle(DefectAnnoInfo defectAnno) {
            var r = defectAnno.rect;
            var typeid = defectAnno.type;

            var rect = new C1.WPF.Chart.Annotation.Rectangle()
            {


                Attachment = C1.Chart.Annotation.AnnotationAttachment.DataCoordinate,
                Position = C1.Chart.Annotation.AnnotationPosition.Center,
                Location = new Point(r.Left + r.Width / 2, r.Top + r.Height / 2),



                Style = new C1.WPF.Chart.ChartStyle()
                {
                    Stroke = getColorByType(typeid),
                    StrokeThickness = 2
                },


            };
            var is_repeatstr = "否";
            if (defectAnno.steel_defect.is_repeat != null && defectAnno.steel_defect.is_repeat==1)
                is_repeatstr = "是";
            //Diff 永钢,南南铝目前可以判断周期性存在的缺陷，兴橙目前不可以
            rect.TooltipText = $"缺陷类型：{DataConverter.ConvertTypeToName(defectAnno.type)}\r\n" +
                                    $"缺陷位置：距左侧{defectAnno.rect.X}毫米 - 距头部{defectAnno.rect.Y / 1000}米\r\n" +
                                    $"缺陷宽高：宽{defectAnno.rect.Width}毫米 × 高{defectAnno.rect.Height}毫米\r\n" +
                                    $"缺陷面积：{defectAnno.steel_defect.real_size}平方毫米"
                                    //+ $"\r\n是否周期出现：{is_repeatstr}"
                                    ;
            rect.SetValue(TagProperty, defectAnno);
            annolayer.Annotations.Add(rect);
        }

        public void AddDefectsAsIcon(DefectAnnoInfo defectAnno)
        {
            var r = defectAnno.rect;
            var typeid = defectAnno.type;
            int size = 2;
            C1.WPF.Chart.Annotation.Shape shapeanno;
            if ((defectAnno.steel_defect as steel_defect).grade==null||(defectAnno.steel_defect as steel_defect).grade != "报警")
            {
                shapeanno = new Circle()
                {
                    Attachment = C1.Chart.Annotation.AnnotationAttachment.DataCoordinate,
                    Position = C1.Chart.Annotation.AnnotationPosition.Center,
                    Location = new Point(r.Left + r.Width / 2, r.Top + r.Height / 2),
                    Radius = 5,
                    Style = new C1.WPF.Chart.ChartStyle()
                    {
                        Fill = getFillColorByType(typeid),
                        Stroke = getColorByType(typeid),
                       
                    },
                };
            }
            else
            {
                shapeanno = new Square()
                {
                    Attachment = C1.Chart.Annotation.AnnotationAttachment.DataCoordinate,
                    Position = C1.Chart.Annotation.AnnotationPosition.Center,
                    Location = new Point(r.Left + r.Width / 2, r.Top + r.Height / 2),
                    Length = 15,
                    Style = new C1.WPF.Chart.ChartStyle()
                    {
                        Fill = getFillColorByType(typeid),
                        Stroke = getColorByType(typeid),
                    },
                };
            }
            var is_repeatstr = "否";
            if (defectAnno.steel_defect.is_repeat != null &&defectAnno.steel_defect.is_repeat==1)
                is_repeatstr = "是";
            //Diff 永钢,南南铝目前可以判断周期性存在的缺陷，兴橙,马钢目前不可以
            shapeanno.TooltipText = $"缺陷类型：{DataConverter.ConvertTypeToName(defectAnno.type)}\r\n" +
                                    $"缺陷位置：距左侧{defectAnno.rect.X.ToString("F1")}毫米 - 距头部{(defectAnno.rect.Y / 1000).ToString("F3")}米\r\n" +
                                    $"缺陷宽高：宽{defectAnno.rect.Width.ToString("F1")}毫米 × 高{defectAnno.rect.Height.ToString("F1")}毫米\r\n" +
                                    $"缺陷面积：{(defectAnno.steel_defect as steel_defect).real_size}平方毫米"
                                    //+$"\r\n是否周期出现：{is_repeatstr}"
                                    + $"\r\n缺陷深度：{(defectAnno.steel_defect as steel_defect).real_depth}"
                                    ;
            shapeanno.SetValue(TagProperty, defectAnno);
            annolayer.Annotations.Add(shapeanno);
        }


        public void AddImage(DefectAnnoInfo defectAnno)
        {
            var r = defectAnno.rect;
            var typeid = defectAnno.type;
            try
            {
                annolayer.Annotations.Clear();
                string imageurl = "";
                var decoder = new PngBitmapDecoder(new Uri(imageurl), BitmapCreateOptions.DelayCreation, BitmapCacheOption.OnDemand);
                var frame = decoder.Frames[0];
                var witdh = frame.PixelWidth;
                var height = frame.PixelHeight;

                BitmapImage bit = new BitmapImage();
                bit.BeginInit();
                bit.UriSource = new Uri(imageurl);
                bit.DecodePixelWidth = witdh / 10;
                bit.DecodePixelHeight = height / 10;
                bit.EndInit();
                bit.Freeze();
                var brush = new ImageBrush(bit);
                brush.Stretch = Stretch.Fill;

                var rect = new C1.WPF.Chart.Annotation.Rectangle()
                {


                    Attachment = C1.Chart.Annotation.AnnotationAttachment.DataCoordinate,
                    Position = C1.Chart.Annotation.AnnotationPosition.Center,
                    Location = new Point(r.Left + r.Width / 2, r.Top + r.Height / 2),



                    Style = new C1.WPF.Chart.ChartStyle()
                    {
                        Fill = new ImageBrush(bit),
                        Stroke = new SolidColorBrush(Colors.Green),

                    },


                };
                rect.SetValue(TagProperty, defectAnno);
                annolayer.Annotations.Add(rect);
                setAxis(defectAnno.rect);

            }
            catch (Exception e)
            {
               
            }


        }

        private void extendAxis(Rect r)
        {
            rulerchart.AxisX.Min = 0;
            rulerchart.AxisY.Min = 0;
            if (r.Right> rulerchart.AxisX.Max)
            {
                rulerchart.AxisX.Max = r.Right;

            }
            if (r.Bottom > rulerchart.AxisY.Max)
            {
                rulerchart.AxisY.Max = r.Bottom;

            }
            rulerchart.AxisX.Scrollbar.Minimum = 0;
            rulerchart.AxisY.Scrollbar.Minimum = 0;
            rulerchart.AxisX.Scrollbar.Maximum = rulerchart.AxisX.Max;
            rulerchart.AxisY.Scrollbar.Maximum = rulerchart.AxisY.Max;

            rulerchart.AxisX.Scrollbar.LowerValue = 0;
            rulerchart.AxisX.Scrollbar.UpperValue = rulerchart.AxisX.Max;
            rulerchart.AxisY.Scrollbar.LowerValue = 0;
            rulerchart.AxisY.Scrollbar.UpperValue = rulerchart.AxisY.Max;


            //rulerchart.AxisY.Scrollbar.LowerValue = 0;
            //Console.WriteLine("LowerValue="+rulerchart.AxisY.Scrollbar.Minimum+",,,"+ rulerchart.AxisY.Scrollbar.Maximum);
        }
        public void RestoreAxis() {
            rulerchart.AxisX.Min = 0;
            rulerchart.AxisY.Min = 0;
            rulerchart.AxisX.Scrollbar.Minimum = 0;
            rulerchart.AxisY.Scrollbar.Minimum = 0;
            rulerchart.AxisX.Scrollbar.Maximum = rulerchart.AxisX.Max;
            rulerchart.AxisY.Scrollbar.Maximum = rulerchart.AxisY.Max;

            rulerchart.AxisX.Scrollbar.LowerValue = 0;
            rulerchart.AxisX.Scrollbar.UpperValue = rulerchart.AxisX.Max;
            rulerchart.AxisY.Scrollbar.LowerValue = 0;
            rulerchart.AxisY.Scrollbar.UpperValue = rulerchart.AxisY.Max;
        }
        private void setAxis(Rect r)
        {
            rulerchart.AxisX.Min = r.Left;
            rulerchart.AxisX.Max = r.Right;
            rulerchart.AxisY.Min = r.Top;
            rulerchart.AxisY.Max = r.Bottom;
        }

        public void setInteractMode(bool caninteract) {
            var mode = caninteract ? GestureMode.XY : GestureMode.None;
            (rulerchart.Behaviors[0] as ZoomBehavior).ZoomMode = mode;
            (rulerchart.Behaviors[1] as TranslateBehavior).TranslationMode = mode;
        }

        #region 渲染时自动设置宽高
        private void flexChart_Rendering(object sender, RenderEventArgs e)
        {
            foreach (var anno in annolayer.Annotations)
            {
                if(anno is C1.WPF.Chart.Annotation.Rectangle) {
                    C1.WPF.Chart.Annotation.Rectangle rect = anno as C1.WPF.Chart.Annotation.Rectangle;

                    SetHeight(rect, (double)((DefectAnnoInfo)rect.GetValue(TagProperty)).rect.Height);
                    SetWidth(rect, (double)((DefectAnnoInfo)rect.GetValue(TagProperty)).rect.Width);
                }

            }

        }

        public void SetHeight(C1.WPF.Chart.Annotation.Rectangle rect, double heightInData)
        {
            double height, min, max;
            Point topPoint, bottomPoint;

            switch (rect.Position)
            {
                case C1.Chart.Annotation.AnnotationPosition.Right:
                case C1.Chart.Annotation.AnnotationPosition.Left:
                case C1.Chart.Annotation.AnnotationPosition.Center:
                    height = heightInData / 2;
                    topPoint = rulerchart.DataToPoint(new Point(rect.Location.X, rect.Location.Y + height));
                    bottomPoint = rulerchart.DataToPoint(new Point(rect.Location.X, rect.Location.Y - height));
                    max = Math.Max(topPoint.Y, bottomPoint.Y);
                    min = Math.Min(topPoint.Y, bottomPoint.Y);
                    rect.Height = max - min;
                    break;

                case C1.Chart.Annotation.AnnotationPosition.Top:
                    topPoint = rulerchart.DataToPoint(new Point(rect.Location.X, rect.Location.Y + heightInData));
                    bottomPoint = rulerchart.DataToPoint(rect.Location);
                    max = Math.Max(topPoint.Y, bottomPoint.Y);
                    min = Math.Min(topPoint.Y, bottomPoint.Y);
                    rect.Height = max - min;
                    break;

                case C1.Chart.Annotation.AnnotationPosition.Bottom:
                    topPoint = rulerchart.DataToPoint(new Point(rect.Location.X, rect.Location.Y - heightInData));
                    bottomPoint = rulerchart.DataToPoint(rect.Location);
                    max = Math.Max(topPoint.Y, bottomPoint.Y);
                    min = Math.Min(topPoint.Y, bottomPoint.Y);
                    rect.Height = max - min;
                    break;
            }
        }

        public void SetWidth(C1.WPF.Chart.Annotation.Rectangle rect, double widthInData)
        {
            double width, min, max;
            Point rightPoint, leftPoint;

            switch (rect.Position)
            {
                case C1.Chart.Annotation.AnnotationPosition.Top:
                case C1.Chart.Annotation.AnnotationPosition.Bottom:
                case C1.Chart.Annotation.AnnotationPosition.Center:
                    width = widthInData / 2;
                    rightPoint = rulerchart.DataToPoint(new Point(rect.Location.X + width, rect.Location.Y));
                    leftPoint = rulerchart.DataToPoint(new Point(rect.Location.X - width, rect.Location.Y));
                    max = Math.Max(rightPoint.X, leftPoint.X);
                    min = Math.Min(rightPoint.X, leftPoint.X);
                    rect.Width = max - min;
                    break;

                case C1.Chart.Annotation.AnnotationPosition.Left:
                    leftPoint = rulerchart.DataToPoint(new Point(rect.Location.X - widthInData, rect.Location.Y));
                    rightPoint = rulerchart.DataToPoint(rect.Location);
                    max = Math.Max(rightPoint.X, leftPoint.X);
                    min = Math.Min(rightPoint.X, leftPoint.X);
                    rect.Width = max - min;
                    break;

                case C1.Chart.Annotation.AnnotationPosition.Right:
                    rightPoint = rulerchart.DataToPoint(new Point(rect.Location.X + widthInData, rect.Location.Y));
                    leftPoint = rulerchart.DataToPoint(rect.Location);
                    max = Math.Max(rightPoint.X, leftPoint.X);
                    min = Math.Min(rightPoint.X, leftPoint.X);
                    rect.Width = max - min;
                    break;
            }
        }
        #endregion
    }
}
